<?php
namespace App\Http\Logic;

use App\Models\SwtAddress;
use App\Models\SwtMarketChains;
use App\Models\SwtNetworkChain;
use App\Models\SwtTradeAccount;
use App\Models\SwtTradeAccountLog;
use App\Models\SwtTradeAddress;
use App\Services\WebThreeService;
use Illuminate\Support\Facades\DB;

class TradeLogic extends BaseLogic
{
    /**
     * @notes 创建钱包账户
     * @param int $user_id
     * @param array $params
     * @return bool|array
     * @author Evil丿
     * @date 2025/03/19 16:15
     */
    public static function createTrade(int $user_id) : bool
    {
        try {
            $trade_info_0 = SwtTradeAccount::create([
                "user_id"        => $user_id,
                "type"           => 0,
            ]);

            if (!$trade_info_0) {
                throw new \Exception(__('coin-type.account_add_fail'));
            }

            $trade_info_1 = SwtTradeAccount::create([
                "user_id"        => $user_id,
                "type"           => 1,
            ]);

            if (!$trade_info_1) {
                throw new \Exception(__('coin-type.trade_add_fail'));
            }

            $list = SwtNetworkChain::with(['network','chain'])->where('default_add', 1) -> get();

            if($list) {
//                $address = SwtAddress::firstWhere('is_used', 0);
//
//                if(!$address) {
//                    self::$error = __('account.address_not_enough');
//                    return false;
//                }

                $data = [];

                foreach($list as $v) {
                    $arr = [
                        [
                            "account_id"     => $trade_info_0->id,
                            "user_id"        => $user_id,
                            "coin_id"        => $v -> chain -> id,
                            "type"           => 0,
                            "network_id"     => $v -> network -> id,
                            "coin"           => $v -> network -> network_name,
                            "chain_name"     => $v -> chain -> base_ccy,
//                            "address"        => $v -> chain -> inst_id == "SWT-USD" ? MD5($user_id) : $address -> address,
                            "address"        => MD5($user_id),
                            "network_name"   => $v -> network -> name,
                            "created_at"     => now(),
                            "updated_at"     => now()
                        ],
                        [
                            "account_id"     => $trade_info_1->id,
                            "user_id"        => $user_id,
                            "coin_id"        => $v -> chain -> id,
                            "type"           => 1,
                            "network_id"     => $v -> network -> id,
                            "coin"           => $v -> network -> network_name,
                            "chain_name"     => $v -> chain -> base_ccy,
//                            "address"        => $v -> chain -> inst_id == "SWT-USD" ? MD5($user_id) : $address -> address,
                            "address"        => MD5($user_id),
                            "network_name"   => $v -> network -> name,
                            "created_at"     => now(),
                            "updated_at"     => now()
                        ]
                    ];

                    $data = array_merge($data, $arr);
                }

                $res = SwtTradeAddress::insert($data);

                if (!$res) {
                    throw new \Exception(__('account.address_bind_error'));
                }

//                $address -> is_used = 1;
//
//                $address -> save();
            }

            return true;
        } catch (\Exception $e) {
            self::$error = $e -> getMessage();
            return false;
        }
    }

    /**
     * @notes 查询余额
     * @param int $user_id
     * @param string $type
     * @param string $quote
     * @return int[]
     * @author Evil丿
     * @date 2025/04/18 14:21
     */
    public static function queryBalance(int $user_id,  string $type, string $quote) : bool|array
    {
        $where = [
            ["user_id", "=", $user_id],
            ["type", "=", $type]
        ];

        $list = SwtTradeAddress::where($where) -> get();

        if(!$list) {
            self::$error = __("account.address_not_found");
            return false;
        }

        $rate = 1;
//        WebThreeService::getRate();

        if($quote == 'USDT') {
            $last = SwtMarketChains::where('inst_id','USDT-USD') -> value('last');
            $rate = $last * $rate;
        }

        $total = 0;
        $lock_total = 0;

        foreach($list as $item) {
            if($quote == 'USDT' || $quote == 'USD') {
                if($item -> chain_name === "USDT") {
                    $total += $item -> total;
                    $lock_total += $item -> lock_total;
                } else {
                    $total += round($item -> total / $rate , 2);
                    $lock_total += round($item -> lock_total / $rate , 2);
                }
            } else {
                if($item -> chain_name === "USDT") {
                    $total += round($item -> total * $rate , 2);
                    $lock_total += round($item -> lock_total * $rate , 2);
                } else {
                    $total += $item -> total;
                    $lock_total += $item -> lock_total;
                }
            }
        }

        $total = round($total, 2);
        $lock_total = round($lock_total, 2);

        return [
            'total' => $total + $lock_total,
            'total_0' => $total,
            'total_1' => $lock_total
        ];
    }

    /**
     * @notes 获得资产列表
     * @param int $user_id
     * @param string $quote
     * @return bool|array
     * @author Evil丿
     * @date 2025/04/21 13:23
     */
    public static function queryAddressBalance(int $user_id, string $quote, string $account_type = "") : bool|array
    {
        $where = [
            ["user_id", '=', $user_id],
            ["type", '=', 1]
        ];

//        if($account_type !== "") {
//            $where[] = ["type", '=', $account_type];
//        }

        $list = SwtTradeAddress::where($where) -> select('chain_name',DB::raw('SUM(total) as all_total')) -> groupBy('chain_name') -> get();

        if(!$list) {
            self::$error =  __("account.address_not_found");
            return false;
        }

        $rate = 1;
//        WebThreeService::getRate();

        if($quote == 'USDT') {
            $last = SwtMarketChains::where('inst_id','USDT-USD') -> value('last');
            $rate = $last * $rate;
        }

        foreach($list as $item) {

            $item -> all_total = round($item -> all_total, 2);

            $item -> num = round($item -> all_total, 2);

            if($quote == 'USDT' || $quote == 'USD') {
                if($item -> chain_name === "SWT") {
                    $item -> all_total = round($item -> all_total / $rate , 2);
                }
            } else {
                if($item -> chain_name === "USDT") {
                    $item -> all_total = round($item -> all_total * $rate , 2);
                }
            }
        }

        return $list -> toArray();
    }

    public static function queryCoinBalance(int $user_id, int $coin_id, int $account_type) : bool|array
    {
        $where = [
            ["user_id", '=', $user_id],
            ["coin_id", '=', $coin_id],
            ["type", '=', $account_type]
        ];

        $total = SwtTradeAddress::where($where) -> value('total');

        if(!$total) {
            self::$error =  __("account.address_not_found");
            return false;
        }

        return ['balance' => $total];
    }

    /**
     * @notes 获取可交易资产余额
     * @param int $user_id
     * @param string $quote
     * @param string $base
     * @return bool|array
     * @author Evil丿
     * @date 2025/04/24 14:57
     */
    public static function queryBuyBalance(int $user_id, string $quote, string $base) : bool|array
    {
        $list = SwtTradeAddress::where('user_id', $user_id) -> where('type', 0) -> whereIn('chain_name',[$base, $quote]) -> get();

        if(!$list) {
            self::$error =  __("account.address_not_found");
            return false;
        }

        $arr = [];

        foreach($list as $v) {
            if($v->chain_name === $base) {
                $arr['base_total'] = $v -> total;
            }

            if($v->chain_name === $quote) {
                $arr['quote_total'] = $v -> total;
            }
        }

        return $arr;
    }

    /**
     * @notes 获取资产交易记录
     * @param int $pageSize
     * @param int $pageNo
     * @return array
     * @author Evil丿
     * @date 2025/04/21 14:16
     */
    public static function queryLogs(int $user_id, int $pageSize, int $pageNo) : array
    {
        $orders = SwtTradeAccountLog::where('user_id', $user_id) -> orderBy('id','desc');

        $pages = $orders -> paginate(
            perPage: $pageSize,
            columns: ['*'],
            pageName: 'pageNo',
            page: $pageNo
        );

        $list = $orders -> get();

        $lang = __('log-text');

        foreach($list as $v) {
            $v -> text = preg_replace_callback('/\{(\w+)\}/', function($matches) use ($lang) {
                return $lang[$matches[1]];
            }, $v -> text);
        }

        return [
            'list'        => $list,
            'pageNo'      => $pages->currentPage(),
            'pageSize'    => $pages->perPage(),
            'count'       => $pages->total(),
            'noMore'      => !$pages->hasMorePages(),
        ];
    }

    /**
     * @notes 发起划转
     * @param int $user_id
     * @param string $coin
     * @param string $num
     * @param int $form
     * @return bool
     * @author Evil丿
     * @date 2025/04/21 14:52
     */
    public static function handleTransfer(int $user_id, string $coin, int|float $num, int $from) : bool
    {
        $to_type = $from == 0 ? 1 : 0;

        $from_info = SwtTradeAddress::where('user_id', $user_id) -> where('type', $from) -> where('chain_name', $coin) -> first();

        if(!$from_info) {
            self::$error = __("coin-type.coin_not_found");
            return false;
        }

        $to_info = SwtTradeAddress::where('user_id', $user_id) -> where('type', $to_type) -> where('chain_name', $coin) -> first();

        if(!$to_info) {
            self::$error = __("coin-type.coin_not_found");
            return false;
        }

        if($from_info -> total < $num) {
            self::$error = __("order.insufficient_balance");
            return false;
        }

        $from_info -> total -= $num;

        $from_info -> save();

        $to_info -> total += $num;

        $to_info -> save();

        $log_data = [
            [
                'address_id'    => $from_info -> id,
                'user_id'       => $user_id,
                'source_type'   => 1,
                'text'          => ($from == 0 ? '{trade_out}' : '{fund_out}') .$num.' '. $coin,
                'change_type'   => 0,
                'change_amount' => $num,
                'created_at'    => now(),
                'updated_at'    => now()
            ],
            [
                'address_id'    => $to_info -> id,
                'user_id'       => $user_id,
                'source_type'   => 1,
                'text'          => ($from == 0 ? '{trade_in}' : '{fund_in}') .$num.' '. $coin,
                'change_type'   => 1,
                'change_amount' => $num,
                'created_at'    => now(),
                'updated_at'    => now()
            ]
        ];

        SwtTradeAccountLog::insert($log_data);

        return true;
    }
}
